package com.authserver.config.oauth2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {


    /*用来配置令牌端点的安全约束，也就是这个端点谁能访问，谁不能访问。
    checkTokenAccess 是指一个 Token 校验的端点，即当第三方应用带着token去访问资源服务器，资源服务器要去校验这个令牌的真实性，
    这个端点我们设置为可以直接访问*/
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("permitAll()") //  资源服务器调用该接口/oauth/check_token，进行校验token有效性
                .allowFormAuthenticationForClients();
    }


    /*用于配置客户端验证的详细信息，该客户端指的是第三方系统的信息
    * 包括appId、appSecret、resourceID、授权类型、授权范围和重定向url
    * 此处暂时先将数据存储在内存中*/
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("appService")
                .secret(new BCryptPasswordEncoder().encode("123"))
                .resourceIds("res1")
                .authorizedGrantTypes("authorization_code","refresh_token")
                .scopes("all")
                .autoApprove(true) //设置自动批准，设置了这个，就不会在弹出页面去确认了
                .redirectUris("http://localhost:8082/index.html");

    }

    /*用来配置令牌的访问端点(授权码模式、简化模式、密码模式、客户端模式)和令牌服务
    * 令牌的访问端点定义使用哪种模式来进行认证
    * 令牌服务定义token存储位置和token的具体信息
    * */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authorizationCodeServices(authorizationCodeServices())
                .tokenServices(authorizationServerTokenServices());
    }
   @Autowired
    TokenStore tokenStore;
    /*客户端服务类，通过该类加载第三方应用的信息*/
    @Autowired
    ClientDetailsService clientDetailsService;

    //注入token服务类
    @Bean
    AuthorizationServerTokenServices authorizationServerTokenServices(){
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore);//设置tokenStrore类
        defaultTokenServices.setSupportRefreshToken(true);//设置是否支持刷新token
        defaultTokenServices.setClientDetailsService(clientDetailsService);
        defaultTokenServices.setAccessTokenValiditySeconds(60*60*2);//设置token的过期时间
        defaultTokenServices.setRefreshTokenValiditySeconds(60*60*24*3);//设置刷新token的过期时间
        return defaultTokenServices;
    }
    //注入授权码服务类
    @Bean
    AuthorizationCodeServices authorizationCodeServices(){
        //使用内存授权码服务类
        return new InMemoryAuthorizationCodeServices();
    }


}
